/* Filename: main.c
 * No.91-92.线程-线程令牌桶1 & 条件变量
 * Description:
 * 调用令牌桶库，读取文件输出到终端
 * Last modified: humble 2020-09-03 14:07:55
 */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include "mytbf.h"

#define CPS (10)
#define BUFLEN (1024)
#define BURST (100)

static volatile int token = 0;

static void usage(void) { printf("Usage:arg[0] <filename>\n"); }

int main(int argc, char **argv)
{
    int wrcnt = 3,
        pos = 0;
    int sfd = 0,
        dfd = 1;
    ssize_t rdlen = 0,
            wrlen = 0;
    char buf[BUFLEN] = {0};
    mytbf_t *tbf = NULL;
    int size = 0;
    int ret = 0;

    if(argc != 2){ fprintf(stderr, "argc != 2\n"); usage(); exit(1); }

    tbf = mytbf_init(CPS, BURST);
    if(!tbf){ fprintf(stderr, "mytbf_init() failed\n"); exit(1); }

    //确保能成功打开
    do{
        sfd = open(argv[1], O_RDONLY);
        if(sfd < 0){
            if(errno != EINTR){ fprintf(stderr, "sfd\n"); usage(); exit(1); }
        }
    }while(sfd < 0);

    while(1){
        size = mytbf_fetch(tbf, BUFLEN);
        if(size < 0){ fprintf(stderr, "mytbf_fetch():%s\n", strerror(-size)); exit(1); }

        while((rdlen = read(sfd, buf, size)) < 0){
            if(errno == EINTR){ continue; }
            fprintf(stderr, "rdlen < 0\n");
            break;
        }

        if(rdlen == 0){ break; }

        if(size - rdlen > 0){
            ret = mytbf_return(tbf, size - rdlen);
            if(ret < 0){ fprintf(stderr, "mytbf_return():%s\n", strerror(-size)); exit(1); }
        }

        pos = 0;
        wrcnt = 3;
        while(rdlen > 0){
            if(--wrcnt < 0){ fprintf(stderr, "write failed\n"); exit(1); }

            wrlen = write(dfd, buf + pos, rdlen);
            if(wrlen < 0){
                if(errno == EINTR){ continue; }
                fprintf(stderr, "wrlen < 0\n");
                exit(1);
            }
            pos += wrlen;
            rdlen -= wrlen;
        }
    }

    close(sfd);
    mytbf_destroy(tbf);
    return 0;
}
